﻿/*
IIS Simple cPanel - A small control panel that allows you to start, stop, recycle sites and/or app pools within IIS.
Copyright(C) 2016 Daniel Osborne (www.dkoz.co.uk)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.

See <http://www.gnu.org/licenses/> for full licensing details
*/

using Microsoft.Web.Administration;
using System;
using System.Security.Principal;
using System.Windows.Forms;
using System.ServiceProcess;
using Microsoft.Win32;
using System.Collections.Generic;
using System.IO;

namespace IISTest
{
    public partial class frmIISTester : Form
    {
        enum Action { Start, Stop, Recycle };
        enum Object { Site, AppPool };

        public frmIISTester()
        {
            InitializeComponent();

            if (IsAdmin() && IsIISInstalled())
                PopulateDropDowns();
            else
                Close();
        }

        private bool IsAdmin()
        {
            bool bIsAdmin = (new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator);

            if (!bIsAdmin)
                MessageBox.Show("Due to the nature of the utility, this application must be ran as Administrator.", "Insufficient Privileges", MessageBoxButtons.OK, MessageBoxIcon.Information);

            return bIsAdmin;
        }

        private bool IsIISInstalled()
        {
            string sIISRegKey = @"Software\Microsoft\InetStp";

            try
            {
                using (RegistryKey iisKey = Registry.LocalMachine.OpenSubKey(sIISRegKey))
                    return (int)iisKey.GetValue("MajorVersion") >= 6;
            }
            catch
            {
                MessageBox.Show("IIS is not installed on this machine, cannot proceed.", "IIS Not Found", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return false;
            }
        }

        private void PopulateDropDowns()
        {
            using (ServerManager mgr = new ServerManager())
            {
                foreach (Site site in mgr.Sites)
                    cboxSiteList.Items.Add(site.Name);

                foreach (ApplicationPool app in mgr.ApplicationPools)
                    cboxAppPoolList.Items.Add(app.Name);
            }

            cboxSiteList.SelectedIndex = 0;
            SetStartStopButtons(cboxSiteList, null);

            cboxAppPoolList.SelectedIndex = 0;
            SetStartStopButtons(cboxAppPoolList, null);
        }

        private void SetStartStopButtons(object sender, EventArgs e)
        {
            ComboBox cbUsed = (ComboBox)sender;
            bool bObjectRunning = false;

            if (cbUsed.Name == "cboxSiteList")
            {
                bObjectRunning = IsObjectRunning(cbUsed.Text, false);

                btnSiteStart.Enabled = !bObjectRunning;
                btnSiteStop.Enabled = bObjectRunning;
            }
            else if (cbUsed.Name == "cboxAppPoolList")
            {
                bObjectRunning = IsObjectRunning(cbUsed.Text, true);

                btnAppStart.Enabled = !bObjectRunning;
                btnAppStop.Enabled = bObjectRunning;
            }
        }

        private bool IsObjectRunning(string p_ObjectName, bool p_bIsAppPool)
        {
            bool bObjectRunning = false;

            using (ServerManager mgr = new ServerManager())
            {
                if (p_bIsAppPool)
                {
                    foreach (ApplicationPool app in mgr.ApplicationPools)
                    {
                        if (app.Name == p_ObjectName)
                            bObjectRunning = (ObjectState.Started == app.State);
                    }
                }
                else
                {
                    foreach (Site s in mgr.Sites)
                    {
                        if (s.Name == p_ObjectName)
                            bObjectRunning = (ObjectState.Started == s.State);
                    }
                }
            }

            return bObjectRunning;
        }

        private void ObjectControlButtons(object sender, EventArgs e)
        {
            Button btnClicked = (Button)sender;
            Object oFocusObject = Object.AppPool;
            Action aSelectedAction = Action.Start;
            string sObjectName = "";

            switch (btnClicked.Name)
            {
                // All Sites/AppPools
                case "btnAllSitesStart":
                    aSelectedAction = Action.Start;
                    oFocusObject = Object.Site;
                    sObjectName = "ALLSITES";
                    break;
                case "btnAllSitesStop":
                    aSelectedAction = Action.Stop;
                    oFocusObject = Object.Site;
                    sObjectName = "ALLSITES";
                    break;
                case "btnAllAppsStart":
                    aSelectedAction = Action.Start;
                    oFocusObject = Object.AppPool;
                    sObjectName = "ALLAPPS";
                    break;
                case "btnAllAppsStop":
                    aSelectedAction = Action.Stop;
                    oFocusObject = Object.AppPool;
                    sObjectName = "ALLAPPS";
                    break;
                case "btnAllAppsRecycle":
                    aSelectedAction = Action.Recycle;
                    oFocusObject = Object.AppPool;
                    sObjectName = "ALLAPPS";
                    break;
                // Specific Sites/AppPools
                case "btnSiteStart":
                    aSelectedAction = Action.Start;
                    oFocusObject = Object.Site;
                    sObjectName = cboxSiteList.Text;
                    break;
                case "btnSiteStop":
                    aSelectedAction = Action.Stop;
                    oFocusObject = Object.Site;
                    sObjectName = cboxSiteList.Text;
                    break;
                case "btnAppStart":
                    aSelectedAction = Action.Start;
                    oFocusObject = Object.AppPool;
                    sObjectName = cboxAppPoolList.Text;
                    break;
                case "btnAppStop":
                    aSelectedAction = Action.Stop;
                    oFocusObject = Object.AppPool;
                    sObjectName = cboxAppPoolList.Text;
                    break;
                case "btnAppRecycle":
                    aSelectedAction = Action.Recycle;
                    oFocusObject = Object.AppPool;
                    sObjectName = cboxAppPoolList.Text;
                    break;
            }
            ControlObject(aSelectedAction, oFocusObject, sObjectName);
        }

        private void ControlObject(Action p_aAction, Object p_oObject, string p_sObjectName)
        {
            using (ServerManager mgr = new ServerManager())
            {
                if (p_oObject == Object.Site)
                {
                    foreach (Site site in mgr.Sites)
                    {
                        if ((site.Name == p_sObjectName) || p_sObjectName == "ALLSITES")
                        {
                            switch (p_aAction)
                            {
                                case Action.Start:
                                    if (site.State != ObjectState.Started)
                                        site.Start();
                                    break;
                                case Action.Stop:
                                    if (site.State != ObjectState.Stopped)
                                        site.Stop();
                                    break;
                                case Action.Recycle:
                                default:
                                    break;
                            }
                        }
                    }
                    SetStartStopButtons(cboxSiteList, null);
                }
                else if (p_oObject == Object.AppPool)
                {
                    foreach (ApplicationPool app in mgr.ApplicationPools)
                    {
                        if ((app.Name == p_sObjectName) || p_sObjectName == "ALLAPPS")
                        {
                            switch (p_aAction)
                            {
                                case Action.Start:
                                    if (app.State != ObjectState.Started)
                                        app.Start();
                                    break;
                                case Action.Stop:
                                    if (app.State != ObjectState.Stopped)
                                        app.Stop();
                                    break;
                                case Action.Recycle:
                                    app.Recycle();
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    SetStartStopButtons(cboxAppPoolList, null);
                }
            }
        }

        private void lnkAbout_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            using (frmAbout frmAbout = new frmAbout())
                frmAbout.ShowDialog();
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfDlg = new SaveFileDialog();
            sfDlg.Title = "Save Export List Location";
            sfDlg.FileName = "IIS Site Export " + DateTime.Now.ToShortDateString().Replace("/", "-") + ".csv";
            sfDlg.Filter = "CSV (Comma Seperated Values)|*.csv|All Files|*.*";

            if(sfDlg.ShowDialog() == DialogResult.OK)
            {
                var sSites = new List<string>();
                sSites.Add("ID,Site Name,Site State,AppPool Name,AppPool Path");
                string sTmpSiteLine = "";

                using (ServerManager mgr = new ServerManager())
                {
                    foreach (Site site in mgr.Sites)
                    {
                        sTmpSiteLine = site.Id + "," + site.Name + "," + site.State + ",";

                        foreach (Microsoft.Web.Administration.Application app in site.Applications)
                        {
                            sTmpSiteLine += app.ApplicationPoolName + ",";

                            foreach (VirtualDirectory dir in app.VirtualDirectories)
                                sTmpSiteLine += dir.PhysicalPath;
                        }

                        sSites.Add(sTmpSiteLine);
                        sTmpSiteLine = "";
                    }
                }

                File.WriteAllLines(sfDlg.FileName, sSites.ToArray());
            }
        }
    }
}
